package club.qwertyzzz;

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.Accessors;

import java.awt.*;
import java.util.Random;

@NoArgsConstructor
public class Tank {
    private int x ;
    private int y ;

    @Getter
    @Setter
    private Dir dir = Dir.DOWN;

    /**
     * 坦克的生存状态，控制在每一帧当中是否执行坦克的相应的操作.
     */
    @Getter
    private boolean living = true;

    @Getter
    @Setter
    private boolean moving = false;

    // 子弹使用这个属性判断子弹自身的阵营
    @Getter
    private TankType type = TankType.player1;
    private TankFrame tf = null;
    public static final int speed = 1;
    public static final int WIDTH = ResourceMgr.player1TankL.getWidth();
    public static final int HEIGHT = ResourceMgr.player1TankL.getHeight();

    // 代表坦克的矩形
    private Rectangle rectangle = null;

    public Tank(int x, int y, Dir dir, boolean moving, TankType type, TankFrame tf) {
        this.x = x;
        this.y = y;
        this.dir = dir;
        this.moving = moving;
        this.type = type;
        this.tf = tf;
    }

    /**
     * 画出坦克, 一帧
     * @param g
     */
    public void paint(Graphics g) {
        // 坦克死亡不执行任何操作
        if(!living)
            return;

        // 根据方向画不同的图片
        g.drawImage(ResourceMgr.getTankImage(dir, type), x, y, null);
        move();

        // 随机的射出一个子弹
        randomFire();

        // 随机一个方向
        randomDir();
    }

    /**
     * 如果坦克处于移动的状态
     * 根据方向和速度，计算坦克下次移动的位置并移动
     */
    private void move() {

        if(!moving)
            return;

        switch(dir) {
            case LEFT:
                x -= speed;
                break;
            case RIGHT:
                x += speed;
                break;
            case UP:
                y -= speed;
                break;
            case DOWN:
                y += speed;
                break;
        }

        // 边界检测，避免坦克出屏幕 todo: 为什么边上会多出几像素？
        if(x < 8 ) x = 8;
        if(y < 30) y = 30;
        if(x + WIDTH > TankFrame.GAME_WIDTH - 8) x = TankFrame.GAME_WIDTH - 8 - WIDTH;
        if(y + HEIGHT > TankFrame.GAME_HEIGHT -8) y = TankFrame.GAME_HEIGHT -8 - HEIGHT;
    }

    /**
     * 敌方坦克随机的射出子弹
     */
    private void randomFire() {
        if(type.isEnemyTank() && tf.getGameRandom().nextInt(100) > 98) {
            fire();
        }
    }

    /**
     * 随机的改变方向移动
     */
    private void randomDir() {
        if(type.isEnemyTank() && tf.getGameRandom().nextInt(100) > 98) {
            dir = Dir.values()[tf.getGameRandom().nextInt(4)];
        }
    }

    /**
     * 开火创建子弹
     */
    public void fire() {

        // 计算子弹发射的位置
        int firePointX = 0, firePointY = 0;
        switch (dir) {
            case LEFT:
                firePointX = x - Bullet.WIDTH;
                firePointY = y + HEIGHT / 2 - Bullet.HEIGHT / 2;
                break;
            case RIGHT:
                firePointX = x + WIDTH;
                firePointY = y + HEIGHT / 2 - Bullet.HEIGHT / 2;
                break;
            case UP:
                firePointX = x + WIDTH / 2 - Bullet.WIDTH / 2;
                firePointY = y - Bullet.HEIGHT;
                break;
            case DOWN:
                firePointX = x + WIDTH / 2 - Bullet.WIDTH / 2;
                firePointY = y + HEIGHT;
                break;
        }

        tf.getBullets().add(new Bullet(firePointX, firePointY, dir, tf, this));

        // 播放子弹发射时的声音
        ResourceMgr.playFireSound();
    }

    /**
     * 销毁坦克
     * 1. 如果是敌方坦克，则直接TankFrame的敌方坦克队列当中删除坦克.
     * todo: 己方坦克怎么处理?
     */
    public void die() {
        tf.getEnemyTanks().remove(this);
        moving = false;
        living = false;

        // 创建一个爆炸效果
        int offsetX = (Blast.WIDTH - WIDTH) / 2, offsetY = (Blast.HEIGHT - HEIGHT) / 2;
        tf.getBlasts().add(new Blast(x - offsetX, y - offsetY, tf));
    }

    /**
     * 获取坦克代表的矩形
     * @return
     */
    public Rectangle rect() {
        if(rectangle == null) {
            rectangle = new Rectangle(x, y, WIDTH, HEIGHT);
        } else {
            rectangle.x = x;
            rectangle.y = y;
            rectangle.width = WIDTH;
            rectangle.height = HEIGHT;
        }
        return rectangle;
    }
}
